home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
comm2
/
mfstlntd.lha
/
telnetd2_0.lha
/
telnetd-2.0
/
source
/
RCS
/
telnetd.c
next >
Wrap
C/C++ Source or Header
|
1995-04-13
|
79KB
|
2,150 lines
head 2.0;
access;
symbols;
locks; strict;
comment @ * @;
2.0
date 95.04.13.19.53.48; author simons; state Exp;
branches;
next 1.11;
1.11
date 95.04.13.18.50.17; author simons; state Exp;
branches;
next 1.10;
1.10
date 95.02.03.00.25.28; author simons; state Exp;
branches;
next 1.9;
1.9
date 95.01.26.22.20.38; author simons; state Exp;
branches;
next 1.8;
1.8
date 95.01.24.00.12.47; author simons; state Exp;
branches;
next 1.7;
1.7
date 95.01.23.23.51.39; author simons; state Exp;
branches;
next 1.6;
1.6
date 95.01.23.23.42.48; author simons; state Exp;
branches;
next 1.5;
1.5
date 95.01.23.23.35.13; author simons; state Exp;
branches;
next 1.4;
1.4
date 95.01.23.22.54.44; author simons; state Exp;
branches;
next 1.3;
1.3
date 95.01.23.22.19.28; author simons; state Exp;
branches;
next 1.2;
1.2
date 95.01.23.21.59.56; author simons; state Exp;
branches;
next 1.1;
1.1
date 95.01.22.18.07.20; author simons; state Exp;
branches;
next ;
desc
@TelnetGetty is called by TnServ and handles the login.
When a correct user is logged in, it executes the listed
command.
@
2.0
log
@Updated my e-mail address to .rhein.de.
Replaced one if-construct with the more efficient ?: operator.
The processname of telnetd is now set to reflect the username
of the user that logged in.
Added LOG_INFO type messages when a login failed or was successful.
@
text
@/*
* $Filename: telnetd.c $
* $Revision: 1.11 $
* $Date: 1995/04/13 18:50:17 $
*
* Copyright (C) 1993,94 by Steve Holland <sdh4@@cornell.edu>
* Copyright (C) 1995 by Peter Simons <simons@@peti.rhein.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: telnetd.c 1.11 1995/04/13 18:50:17 simons Exp simons $
*
*/
/************************************* includes ***********/
#include <exec/types.h>
#include <exec/memory.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/usergroup.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <exec/errors.h>
#include <devices/serial.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inetd.h>
#include <syslog.h>
#include <amitcp/socketbasetags.h>
#include <fakesr.h>
#include "telnetd_rev.h"
/************************************* structures *********/
struct InstData {
struct Library *DOSB;
struct Library *SocketB;
struct Library *UtilityB;
struct Library *UserGroupB;
int Socket;
signed short RecvBuf[1024];
int RecvBufPos;
int RecvBufFlags;
};
struct PasswdInfo {
char Login[50];
char Passwd[50];
char RealName[150];
char WorkDir[256];
char Command[512];
};
/************************************* defines ************/
#define DOSBase Inst->DOSB
#define UtilityBase Inst->UtilityB
#define SocketBase Inst->SocketB
#define UserGroupBase Inst->UserGroupB
#define Socket Inst->Socket
/* telnet symbols */
#define IAC 255
#define WILL 251
#define WONT 252
#define DO 253
#define DONT 254
#define ECHO 1
#define LINEMODE 34
#define SE 240
#define SB 250
#define MODE 1
#define EDIT 1
#define RBF_SUBNEGOTIATE (1<<0) /* Defines for RecvBufFlags */
/************************************* global variables ***/
static const char __DOSVer[] = VERSTAG " written by Peter Simons <simons@@peti.rhein.de>";
#ifndef USE_INETD
struct Library *SysBase;
#endif
char *Signature="FAKEMSG--EXPUNGE";
/************************************* prototypes *********/
void SockPuts(struct InstData *Inst,int Sock,char *Buf);
void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize);
unsigned long GetInt(char *String,char **NewPtr);
struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login);
int __asm SubSubProc(register __a0 char *ArgString,register __d0 long Length);
struct DosPacket *PktFromMsg(struct Message *Msg);
void MakeLongStr(char *StrBuf,unsigned long Num);
void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag);
int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode);
struct Process *MyCreateNewProcTags(struct InstData *,ULONG,...);
void *MyAllocDosObjectTags(struct InstData *,ULONG,ULONG,...);
void PktFPuts(struct InstData *Inst,BPTR File,char *String);
void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len);
void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...);
void mystrcat(char *Dest,char *Cat);
void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...);
ULONG FakeBeginIO(void *IORequest);
ULONG FakeAbortIO(void *IORequest);
ULONG FakeOpen(void *IORequest);
ULONG FakeClose(void *IORequest);
void mymovmem(char *From,char *To,int Len);
#define NewList(list) {(list)->lh_Head=(struct Node *)&(list)->lh_Tail;(list)->lh_Tail=NULL;(list)->lh_TailPred=(struct Node *)&(list)->lh_Head;}
#ifdef DEBUG
BPTR DebugFile;
#endif
#ifdef USE_INETD
int main(void)
#else
int __asm main(register __a0 char *ArgStr,register __d0 long Length)
/* ArgString will look like: "[SocketID] [SigNum] [ParentTaskID]" */
#endif
{
int Cnt;
unsigned long SockID,SigID,TaskID;
char Buf[1000],LoginBuf[50], MyPrgName[64];
BPTR BannerFile=NULL;
struct InstData *Inst=NULL;
struct PasswdInfo *Info=NULL;
struct FileHandle *FH;
struct Message *Msg,*GotMsg;
unsigned char NoEcho[7];
unsigned char Echo[14];
char *ArgString;
int OpenCount=0;
int AmntRead;
int HangupFlag=FALSE;
ULONG SigMask;
long yes=TRUE;
fd_set RdSet;
fd_set WrSet;
struct List ReadWaitList;
struct DosPacket *Pkt;
int Err;
unsigned char Chr,NumBuf[30];
int RawMode=FALSE;
int NextChar=-1;
struct MsgPort *TimePort;
struct timerequest *TimeReq;
struct DaemonMessage *InetdStartup;
struct Process *Self;
#ifndef USE_INETD
SysBase=*((struct Library **)0x00000004);
ArgString=ArgStr;
#endif
Echo[0]=NoEcho[0]=IAC;
Echo[1]=WONT;
Echo[2]=ECHO;
Echo[3]=IAC;
Echo[4]=DO;
Echo[5]=LINEMODE;
Echo[6]=IAC;
Echo[7]=SB;
Echo[8]=LINEMODE;
Echo[9]=MODE;
Echo[10]=EDIT;
Echo[11]=IAC;
Echo[12]=SE;
NoEcho[1]=WILL;
NoEcho[2]=ECHO;
NoEcho[3]=IAC;
NoEcho[4]=DONT;
NoEcho[5]=LINEMODE;
Echo[13]=NoEcho[6]='\0';
#ifndef USE_INETD
for (Cnt=0;Cnt < Length;Cnt++) {
if (ArgStr[Cnt]!=' ' && (ArgStr[Cnt] < '0' || ArgStr[Cnt] > '9'))
return ERROR_FILE_NOT_OBJECT;
}
#endif
Inst=AllocMem(sizeof(struct InstData),MEMF_CLEAR);
if (!Inst) return 0;
DOSBase=OpenLibrary("dos.library",36);
UtilityBase=OpenLibrary("utility.library",36);
SocketBase=OpenLibrary("bsdsocket.library",2);
UserGroupBase=OldOpenLibrary(USERGROUPNAME);
TimePort=CreateMsgPort();
NewList(&ReadWaitList);
if (!DOSBase || !UtilityBase || !SocketBase || !UserGroupBase || !TimePort) return 0;
SocketBaseTags(SBTM_SETVAL(SBTC_LOGTAGPTR), "telnetd",
SBTM_SETVAL(SBTC_LOGSTAT), 0,
SBTM_SETVAL(SBTC_LOGFACILITY), LOG_AUTH,
TAG_END);
#ifdef DEBUG
DebugFile=Open("con:0/0/500/100/telnetd DEBUG/WAIT/CLOSE",MODE_OLDFILE);
FPuts(DebugFile,"telnetd starting\n");
# ifndef USE_INETD
FPuts(DebugFile,"ArgString=");
FPuts(DebugFile,ArgString);
FPuts(DebugFile,"\n");
# endif
#endif
#ifdef USE_INETD
Self=(struct Process *) FindTask(NULL);
InetdStartup=(struct DaemonMessage *)Self->pr_ExitData;
if (!InetdStartup) goto quit;
Socket=ObtainSocket(InetdStartup->dm_Id,InetdStartup->dm_Family,InetdStartup->dm_Type,0);
if (Socket < 0) goto quit;
#else
/* Get arguments */
SockID=GetInt(ArgString,&ArgString);
ArgString++; /* Skip over space */
SigID=GetInt(ArgString,&ArgString);
ArgString++; /* Skip over space */
TaskID=GetInt(ArgString,&ArgString);
/* After this call, the parameter string is no longer valid */
Signal((struct Task *)TaskID,1<<SigID);
#ifdef DEBUG
FPuts(DebugFile,"Signaled parent\n");
#endif
/* We're on our own now */
Socket=ObtainSocket(SockID,AF_INET,SOCK_STREAM,0);
if (Socket < 0) goto quit;
#endif
#ifdef DEBUG
FPuts(DebugFile,"Got Socket\n");
#endif
/* First, display banner, ask for password, etc */
if (BannerFile=Open("AmiTCP:db/telnetd_banner",MODE_OLDFILE)) {
int len = 1;
while(TRUE) {
len = Read(BannerFile, Buf, sizeof(Buf));
if (!len || len == -1)
break;
SockWrite(Inst,Socket,Buf,len,FALSE);
}
Close(BannerFile);
}
#ifdef DEBUG
FPuts(DebugFile,"Wrote banner to socket\n");
#endif
/* Get login name */
SockPuts(Inst,Socket,"Login: ");
SockPuts(Inst,Socket,Echo);
SockGets(Inst,Socket,LoginBuf,sizeof(LoginBuf));
while (strlen(LoginBuf) && (LoginBuf[strlen(LoginBuf)-1]=='\n' || LoginBuf[strlen(LoginBuf)-1]=='\r'))
LoginBuf[strlen(LoginBuf)-1]='\0';
#ifdef DEBUG
FPuts(DebugFile,"Got Login: ");
FPuts(DebugFile,LoginBuf);
FPuts(DebugFile,"\n");
#endif
Info = LookupPasswd(Inst, LoginBuf);
/*
* We don't need a password if the password is "*"
* AND the shell is not equal "nologin".
*
* Otherwise get a password, even if the user doesn't exist at all.
*/
if (!Info || !(!strcmp(Info->Passwd, "*") && strcmp("nologin", Info->Command))) {
strcpy(Buf, "Password: ");
strcpy(Buf+strlen(Buf), NoEcho);
SockPuts(Inst, Socket, Buf);
SockGets(Inst, Socket, Buf,sizeof(Buf));
while (strlen(Buf) && (Buf[strlen(Buf)-1]=='\n' || Buf[strlen(Buf)-1]=='\r'))
Buf[strlen(Buf)-1]='\0';
SockPuts(Inst,Socket,Echo);
#ifdef DEBUG
FPuts(DebugFile,"Got Password: ");
FPuts(DebugFile,Buf);
FPuts(DebugFile,"\n");
#endif
if (!Info || !strcmp("nologin", Info->Command) || strcmp(Info->Passwd, crypt(Buf, Info->Passwd))) {
if (Info)
syslog(LOG_INFO, "Unsuccessful login attempt from user %s", Info->Login);
SockPuts(Inst,Socket,"\nLogin incorrect.\nClosing connection\n");
CloseSocket(Socket);
goto quit;
}
}
SockPuts(Inst,Socket,"\n");
syslog(LOG_INFO, "User %s logged in successfully", Info->Login);
sprintf(MyPrgName, "telnetd <%s>", Info->Login);
SetProgramName(MyPrgName);
if (Info->Command[0]=='*') {
/* Use stdin/stdout */
/* Make myself a filehandle */
#ifdef DEBUG
FPuts(DebugFile,"Logged in OK\nMaking Filehandle\n");
#endif
FH=MyAllocDosObjectTags(Inst,DOS_FILEHANDLE,ADO_FH_Mode,MODE_OLDFILE,TAG_END);
if (!FH) goto quit;
FH->fh_Pos=FH->fh_End=-1;
FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
FH->fh_Args=(LONG)Info;
FH->fh_Port=FH->fh_Type; /* Is this right? */
FH=(struct FileHandle *)MKBADDR(FH);
OpenCount++;
/* Run the subprocess */
MakeLongStr(Buf,(ULONG)FH);
strcpy(Buf+strlen(Buf)," ");
strcpy(Buf+strlen(Buf),Info->Command+1 /* ignore the leading '*' */);
#ifdef DEBUG
FPuts(DebugFile,"Starting subprocess\nCmdLine=");
FPuts(DebugFile,Buf);
FPuts(DebugFile,"\n");
/*Close(DebugFile);*/
Flush(DebugFile);
/*DebugFile=NULL;*/
#endif
/* NO more DOS calls allowed after this one */
/* We also can't use Buf after we make this call */
if (*(Info->Command+1)) {
MyCreateNewProcTags(Inst,NP_Entry,SubSubProc,
NP_Arguments,Buf,
TAG_END);
}
FD_ZERO(&RdSet);
IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Starting handler support\n");
#endif
for (;;) {
if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
if (NextChar != -1) {
Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
*(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
Chr=NextChar;
NextChar=-1;
Err=1;
Pkt->dp_Res1++;
if (Pkt->dp_Res1==Pkt->dp_Arg3 || Chr=='\r' || Chr=='\n') {
Remove(ReadWaitList.lh_Head);
PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
}
}
}
if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
FD_SET(Socket,&RdSet);
} else {
FD_CLR(Socket,&RdSet);
}
SigMask=(1<<((struct Process *)FindTask(NULL))->pr_MsgPort.mp_SigBit)|(1<<TimePort->mp_SigBit);
WaitSelect(Socket+1,&RdSet,NULL,NULL,NULL,&SigMask);
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Wait ended \n");
#endif
if (FD_ISSET(Socket,&RdSet)) {
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Got read available from socket\n");
#endif
if (ReadWaitList.lh_Head->ln_Succ) {
/* Someone is waiting to read */
Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
if (Pkt && Pkt->dp_Type==ACTION_READ) {
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Performing delayed read\n");
#endif
while (Pkt->dp_Res1 < Pkt->dp_Arg3) {
if (NextChar != -1) {
*(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
Chr=NextChar;
NextChar=-1;
Err=1;
} else {
Err=RecvChar(Inst,Socket,((char *)Pkt->dp_Arg2)+Pkt->dp_Res1,FALSE/*RawMode*/);
Chr=*(((char *)Pkt->dp_Arg2)+Pkt->dp_Res1);
}
if (Err==1) Pkt->dp_Res1++;
else if (Err==0) {
/* Hangup */
HangupFlag=TRUE;
break;
} else break;
#ifdef DEBUG
if (Chr==255) {
PktFPuts(Inst,DebugFile,"Received 255\n");
}
#endif
if (Chr=='\r' || Chr=='\n') {
break;
}
}
if (Err==1) {
if (Pkt->dp_Res1==Pkt->dp_Arg3 ||
Chr=='\r' || Chr=='\n') {
Remove(ReadWaitList.lh_Head);
/* syslog(LOG_DEBUG, "Sending out \"%s\"",
* &Pkt->dp_Link+sizeof(struct Message));
*/
PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
}
}
} else if (Pkt && Pkt->dp_Type==ACTION_WAIT_CHAR) {
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Processing WAIT_CHAR");
#endif
if (NextChar==-1) {
Err=RecvChar(Inst,Socket,&Chr,FALSE);
if (Err==1) {
Pkt->dp_Res1=DOSTRUE;
Remove(ReadWaitList.lh_Head);
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"char ready\n");
#endif
AbortIO((struct IORequest *)Pkt->dp_Res2);
WaitIO((struct IORequest *)Pkt->dp_Res2);
CloseDevice((struct IORequest *)Pkt->dp_Res2);
DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
Pkt->dp_Res2=0;
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
NextChar=Chr;
} else {
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"no char available\n");
#endif
NextChar=-1;
}
if (Err==0) HangupFlag=TRUE;
} else {
Pkt->dp_Res1=DOSTRUE;
Remove(ReadWaitList.lh_Head);
AbortIO((struct IORequest *)Pkt->dp_Res2);
WaitIO((struct IORequest *)Pkt->dp_Res2);
CloseDevice((struct IORequest *)Pkt->dp_Res2);
DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
Pkt->dp_Res2=0;
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"char ready\n");
#endif
}
}
else { /* Invalid message */
Remove(ReadWaitList.lh_Head);
}
} else {
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Unexpected: got read ready, no request\n");
#endif
}
}
while (TimeReq=(struct timerequest *)GetMsg(TimePort)) {
Msg=(struct Message *)TimeReq->tr_node.io_Message.mn_Node.ln_Name;
Pkt=PktFromMsg(Msg);
CloseDevice(TimeReq);
DeleteIORequest(TimeReq);
Pkt->dp_Res1=DOSFALSE;
Pkt->dp_Res2=0;
Remove(Msg); /* Remove it from the read wait list */
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
}
while (Msg=GetMsg(&((struct Process *)FindTask(NULL))->pr_MsgPort)) {
Pkt=PktFromMsg(Msg);
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Got packet\n");
#endif
switch(Pkt->dp_Type) {
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT:
case ACTION_FINDUPDATE:
FH=(struct FileHandle *)BADDR((BPTR)Pkt->dp_Arg1);
FH->fh_Pos=FH->fh_End=-1;
FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
FH->fh_Args=(LONG)Info;
FH->fh_Port=FH->fh_Type; /* Is this right? */
OpenCount++;
Pkt->dp_Res1=DOSTRUE;
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
break;
case ACTION_READ:
Pkt->dp_Res1=0;
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Got action_read\n");
#endif
AddTail(&ReadWaitList,Msg);
break;
case ACTION_WRITE:
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Got action_write\n");
#endif
SockWrite(Inst,Socket,(char *)Pkt->dp_Arg2,Pkt->dp_Arg3,FALSE/*RawMode*/);
Pkt->dp_Res1=Pkt->dp_Arg3;
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
break;
case ACTION_WAIT_CHAR:
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Got action_waitchar");
#endif
Pkt->dp_Res1=DOSFALSE;
TimeReq=CreateIORequest(TimePort,sizeof(struct timerequest));
if (!TimeReq || OpenDevice("timer.device",UNIT_MICROHZ,TimeReq,0)) {
if (TimeReq)
DeleteIORequest(TimeReq);
Pkt->dp_Res2=ERROR_NO_FREE_STORE;
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
}
TimeReq->tr_node.io_Command=TR_ADDREQUEST;
TimeReq->tr_time.tv_micro=Pkt->dp_Arg1;
TimeReq->tr_time.tv_secs=0;
TimeReq->tr_node.io_Message.mn_Node.ln_Name=Msg;
SendIO(TimeReq);
Pkt->dp_Res2=(ULONG)TimeReq;
AddTail(&ReadWaitList,Msg);
break;
/*
case ACTION_DISKINFO:
break;
*/
case ACTION_SCREEN_MODE:
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Got action_screen_mode\n");
#endif
if (Pkt->dp_Arg1) {
/* Raw mode */
SockPuts(Inst,Socket,NoEcho);
RawMode=TRUE;
} else {
SockPuts(Inst,Socket,Echo);
RawMode=FALSE;
}
Pkt->dp_Res1=DOSFALSE;
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
break;
case ACTION_END:
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Got action_end\n");
#endif
Pkt->dp_Res1=0;
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
OpenCount--;
if (!OpenCount) {
for (GotMsg=(struct Message *)ReadWaitList.lh_Head;GotMsg->mn_Node.ln_Succ;GotMsg=(struct Message *)GotMsg->mn_Node.ln_Succ) {
Pkt=PktFromMsg(GotMsg);
if (Pkt->dp_Type==ACTION_WAIT_CHAR) {
AbortIO((struct IORequest *)Pkt->dp_Res2);
WaitIO((struct IORequest *)Pkt->dp_Res2);
CloseDevice((struct IORequest *)Pkt->dp_Res2);
DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
Pkt->dp_Res2=0;
}
}
goto quit;
}
break;
case ACTION_SEEK:
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Got action_seek\n");
#endif
Pkt->dp_Res1=-1;
Pkt->dp_Res2=ERROR_OBJECT_WRONG_TYPE;
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
break;
default:
#ifdef DEBUG
PktFPuts(Inst,DebugFile,"Got action_not_known. Number");
MakeLongStr(NumBuf,Pkt->dp_Type);
PktFPuts(Inst,DebugFile,NumBuf);
PktFPuts(Inst,DebugFile,"\n");
#endif
Pkt->dp_Res1=0;
Pkt->dp_Res2=ERROR_ACTION_NOT_KNOWN;
PutMsg(Pkt->dp_Port,Pkt->dp_Link);
}
}
}
} else {
/* Use fake serial */
struct IOStdReq *IOReq=NULL;
struct MsgPort *IOPort=NULL;
struct FSRUnit *SerUnit=NULL;
/* SerUnit->fsru_UserData[0]=CmdPort
SerUnit->fsru_UserData[1]=ReadQueue
SerUnit->fsru_UserData[2]=WriteQueue
SerUnit->fsru_UserData[3]=Open count
SerUnit->fsru_UserData[4]=RBufLen */
struct MsgPort *CmdPort=NULL;
struct List *ReadQueue=NULL;
struct List *WriteQueue=NULL;
char *CmdPtr;
struct IOExtSer *GotReq=NULL,*OtrReq=NULL;
char *RBuf=NULL;
int RBufPos=0;
int SerUnitAdded=FALSE;
int Amnt;
int RecvRet;
int CD=TRUE; /* Carrier Detect */
long UnitNum=FSR_UNITNONE;
/* We use IOExtSer.Status bit 0 as a flag to say whether this request has
been aborted */
#ifdef DEBUG
FPuts(DebugFile,"Creating ports...\n");
#endif
IOPort=CreateMsgPort();
CmdPort=CreateMsgPort();
IOReq=CreateIORequest(IOPort,sizeof(struct IOStdReq));
if (!IOPort || !IOReq || !CmdPort) {
#ifdef DEBUG
FPuts(DebugFile,"Unable to create message port/IORequest\nExiting\n");
#endif
goto quitfakeser;
}
#ifdef DEBUG
FPuts(DebugFile,"Opening fakesr.device...\n");
#endif
if (OpenDevice("fakesr.device",FSR_CTLUNIT,IOReq,0)) {
IOReq->io_Device=NULL;
#ifdef DEBUG
FPuts(DebugFile,"Unable to open fakesr.device\nExiting\n");
#endif
goto quitfakeser;
}
#ifdef DEBUG
FPuts(DebugFile,"opened successfully\n");
#endif
SerUnit=AllocMem(sizeof(struct FSRUnit),MEMF_CLEAR|MEMF_PUBLIC);
ReadQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
if (ReadQueue) NewList(ReadQueue);
WriteQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
if (WriteQueue) NewList(WriteQueue);
if (!SerUnit || !ReadQueue || !WriteQueue) {
#ifdef DEBUG
FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
#endif
goto quitfakeser;
}
CmdPtr=Info->Command;
if (Info->Command[0]<='9' && Info->Command[0] >= '0') {
UnitNum=GetInt(Info->Command,&CmdPtr);
}
SerUnit->fsru_Num=UnitNum;
SerUnit->fsru_BeginIO=FakeBeginIO;
SerUnit->fsru_AbortIO=FakeAbortIO;
SerUnit->fsru_Open=FakeOpen;
SerUnit->fsru_Close=FakeClose;
SerUnit->fsru_UserData[0]=CmdPort;
SerUnit->fsru_UserData[1]=ReadQueue;
SerUnit->fsru_UserData[2]=WriteQueue;
SerUnit->fsru_UserData[3]=0;
SerUnit->fsru_UserData[4]=(void *)1024;
IOReq->io_Data=(APTR)SerUnit;
IOReq->io_Length=sizeof(*SerUnit);
IOReq->io_Command=FSRCMD_ADDUNIT;
IOReq->io_Error=0;
#ifdef DEBUG
FPuts(DebugFile,"Adding FakeSr unit...");
#endif
DoIO(IOReq);
if (IOReq->io_Error) {
#ifdef DEBUG
FPuts(DebugFile,"Error adding fakesr.device unit\nExiting\n");
#endif
goto quitfakeser;
}
SerUnitAdded=TRUE;
#ifdef DEBUG
FPuts(DebugFile,"Done\n");
#endif
RBuf=AllocMem((ULONG)SerUnit->fsru_UserData[4],MEMF_PUBLIC);
RBufPos=0;
if (!RBuf) {
#ifdef DEBUG
FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
#endif
goto quitfakeser;
}
IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
{
BPTR NilInput,NilOutput;
#ifdef DEBUG
FPuts(DebugFile,"Opening filehandles\n");
#endif
if (*CmdPtr) {
NilInput=Open("NIL:",MODE_OLDFILE);
NilOutput=Open("NIL:",MODE_OLDFILE);
/* sprintf(Buf,"%s -DEVICE fakesr.device -UNIT %ld",CmdPtr,SerUnit->fsru_Num); */
strcpy(Buf,CmdPtr);
mystrcat(Buf," -DEVICE fakesr.device -UNIT ");
MakeLongStr(LoginBuf,SerUnit->fsru_Num);
#ifdef DEBUG
FPuts(DebugFile,"Got FakeSr unit: ");
FPuts(DebugFile,LoginBuf);
FPuts(DebugFile,"\n");
#endif
SockPuts(Inst,Socket,NoEcho);
mystrcat(Buf,LoginBuf);
#ifdef DEBUG
FPuts(DebugFile,"Running command:");
FPuts(DebugFile,Buf);
FPuts(DebugFile,"\n");
#endif
MySystemTags(DOSBase,Buf,SYS_Input,NilInput,SYS_Output,NilOutput,SYS_Asynch,TRUE,TAG_END);
}
}
for (;;) {
FD_ZERO(&RdSet);
FD_ZERO(&WrSet);
if (CD) {
if (RBufPos < (((long)SerUnit->fsru_UserData[4])-1)) FD_SET(Socket,&RdSet);
if (WriteQueue->lh_Head->ln_Succ) FD_SET(Socket,&WrSet);
}
SigMask=(1<<CmdPort->mp_SigBit)|SIGBREAKF_CTRL_C;
WaitSelect(Socket+1,&RdSet,&WrSet,NULL,NULL,&SigMask);
#ifdef DEBUG
FPuts(DebugFile,"Wait ended...");
#endif
if (FD_ISSET(Socket,&RdSet)) {
while ((RBufPos < (long)SerUnit->fsru_UserData[4]) && ((RecvRet=RecvChar(Inst,Socket,RBuf+RBufPos,TRUE))==1)) RBufPos++;
Forbid();
if ((GotReq=(struct IOExtSer *)ReadQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
Remove(GotReq);
Permit();
Amnt=min(RBufPos,GotReq->IOSer.io_Length);
memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
GotReq->IOSer.io_Actual+=Amnt;
if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,RBufPos-Amnt);
RBufPos-=Amnt;
if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
if (GotReq->io_Status & (1<<0)) {
/* We got an AbortIO() */
GotReq->IOSer.io_Error=IOERR_ABORTED;
ReplyMsg(GotReq);
} else {
Forbid();
AddTail(ReadQueue,GotReq);
Permit();
}
}
else ReplyMsg(GotReq);
}
else Permit();
if (RecvRet==0) {
/* Connection closed */
CD=FALSE;
}
}
if (FD_ISSET(Socket,&WrSet)) {
Forbid();
if ((GotReq=(struct IOExtSer *)WriteQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
Remove(GotReq);
Permit();
#ifdef DEBUG
FPuts(DebugFile,"Writing to socket\n");
MyFPrintf(Inst,DebugFile,"io_Actual=%ld,io_Length=%ld\n",(long)GotReq->IOSer.io_Actual,(long)GotReq->IOSer.io_Length);
#endif
SockWrite(Inst,Socket,((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,GotReq->IOSer.io_Length-GotReq->IOSer.io_Actual,TRUE);
#ifdef DEBUG
FPuts(DebugFile,"Write completed\n");
#endif
GotReq->IOSer.io_Actual=GotReq->IOSer.io_Length;
if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
Forbid();
if (GotReq->io_Status & (1<<0)) {
Permit();
/* We got an AbortIO() */
GotReq->IOSer.io_Error=IOERR_ABORTED;
ReplyMsg(GotReq);
} else {
AddTail(WriteQueue,GotReq);
Permit();
}
} else {
#ifdef DEBUG
FPuts(DebugFile,"Replying write message\n");
#endif
ReplyMsg(GotReq);
}
} else {
Permit();
}
}
while (GotReq=(struct IOExtSer *)GetMsg(CmdPort)) {
if (GotReq->IOSer.io_Message.mn_Node.ln_Name==Signature) {
/* We just use the pointer as a signature */
/* We just got an expunge request */
#ifdef DEBUG
FPuts(DebugFile,"Got expunge request\n");
#endif
FreeMem(GotReq,sizeof(struct Message)); /* We free the expunge request instead of reply */
Forbid();
if (SerUnit->fsru_UserData[3]==0) {
/* Open count==0 */
if (SerUnitAdded) {
IOReq->io_Command=FSRCMD_REMUNIT;
IOReq->io_Data=(APTR)SerUnit;
IOReq->io_Length=sizeof(*SerUnit);
DoIO(IOReq);
SerUnitAdded=FALSE;
}
if (SerUnit->fsru_UserData[3]==0) {
/* If opencnt is still 0 */
Permit();
goto quitfakeser; /* exit */
}
}
Permit();
}
else {
#ifdef DEBUG
FPuts(DebugFile,"Got cmd...");
#endif
switch(GotReq->IOSer.io_Command) {
case CMD_CLEAR:
#ifdef DEBUG
FPuts(DebugFile,"Got CMD_CLEAR\n");
#endif
RBufPos=0;
GotReq->IOSer.io_Error=0;
ReplyMsg(GotReq);
break;
case CMD_FLUSH:
case CMD_RESET:
#ifdef DEBUG
FPuts(DebugFile,"Got CMD_FLUSH/RESET\n");
#endif
Forbid();
while (OtrReq=(struct IOExtSer *)RemHead(ReadQueue)) {
OtrReq->IOSer.io_Error=IOERR_ABORTED;
ReplyMsg(OtrReq);
}
while (OtrReq=(struct IOExtSer *)RemHead(WriteQueue)) {
OtrReq->IOSer.io_Error=IOERR_ABORTED;
ReplyMsg(OtrReq);
}
Permit();
GotReq->IOSer.io_Error=0;
ReplyMsg(GotReq);
break;
case CMD_READ:
#ifdef DEBUG
FPuts(DebugFile,"Got CMD_READ\n");
#endif
GotReq->IOSer.io_Actual=0;
GotReq->IOSer.io_Error=0;
Amnt=min(RBufPos,GotReq->IOSer.io_Length);
memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
GotReq->IOSer.io_Actual+=Amnt;
if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,Amnt);
RBufPos-=Amnt;
if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
Forbid();
AddTail(ReadQueue,GotReq);
Permit();
}
else ReplyMsg(GotReq);
break;
case CMD_START:
#ifdef DEBUG
FPuts(DebugFile,"Got CMD_START\n");
#endif
GotReq->IOSer.io_Error=0;
ReplyMsg(GotReq);
break;
case CMD_STOP:
#ifdef DEBUG
FPuts(DebugFile,"Got CMD_STOP\n");
#endif
GotReq->IOSer.io_Error=0;
ReplyMsg(GotReq);
break;
case CMD_WRITE:
#ifdef DEBUG
FPuts(DebugFile,"Got CMD_WRITE\n");
#endif
GotReq->IOSer.io_Actual=0;
GotReq->IOSer.io_Error=0;
Forbid();
AddTail(WriteQueue,GotReq);
Permit();
break;
case SDCMD_BREAK:
#ifdef DEBUG
FPuts(DebugFile,"Got SDCMD_BREAK\n");
#endif
GotReq->IOSer.io_Error=0;
ReplyMsg(GotReq);
break;
case SDCMD_QUERY:
#ifdef DEBUG
FPuts(DebugFile,"Got SDCMD_QUERY\n");
#endif
GotReq->IOSer.io_Actual=RBufPos;
GotReq->io_Status=0x0000 | ((CD) ? 0:(1<<5));
GotReq->IOSer.io_Error=0;
ReplyMsg(GotReq);
break;
case SDCMD_SETPARAMS:
#ifdef DEBUG
FPuts(DebugFile,"Got SDCMD_SETPARAMS\n");
#endif
GotReq->IOSer.io_Error=0;
ReplyMsg(GotReq);
break;
default:
#ifdef DEBUG
FPuts(DebugFile,"Got CMD_UNKNOWN\n");
#endif
GotReq->IOSer.io_Error=IOERR_NOCMD;
ReplyMsg(GotReq);
}
}
}
}
quitfakeser:
if (ReadQueue) {
Forbid();
while (GotReq=(struct IOExtSer *)RemHead(ReadQueue)) {
GotReq->IOSer.io_Error=IOERR_ABORTED;
GotReq->IOSer.io_Actual=0;
ReplyMsg(GotReq);
}
Permit();
FreeMem(ReadQueue,sizeof(struct List));
}
if (WriteQueue) {
Forbid();
while (GotReq=(struct IOExtSer *)RemHead(WriteQueue)) {
GotReq->IOSer.io_Error=IOERR_ABORTED;
GotReq->IOSer.io_Actual=0;
ReplyMsg(GotReq);
}
Permit();
FreeMem(WriteQueue,sizeof(struct List));
}
if (RBuf && SerUnit) {
FreeMem(RBuf,(long)SerUnit->fsru_UserData[4]);
}
if (SerUnit) {
if (SerUnitAdded && IOReq) {
IOReq->io_Data=(APTR)SerUnit;
IOReq->io_Length=sizeof(*SerUnit);
IOReq->io_Command=FSRCMD_REMUNIT;
DoIO(IOReq);
}
FreeMem(SerUnit,sizeof(struct FSRUnit));
}
if (IOReq) {
if (IOReq->io_Device) CloseDevice(IOReq);
DeleteIORequest(IOReq);
}
if (IOPort) DeleteMsgPort(IOPort);
if (CmdPort) DeleteMsgPort(CmdPort);
goto quit;
}
quit:
#ifdef DEBUG
if (DebugFile) Close(DebugFile);
#endif
SocketBaseTags(SBTM_SETVAL(SBTC_LOGTAGPTR), NULL, TAG_END);
if (TimePort) DeleteMsgPort(TimePort);
if (Info) FreeMem(Info,sizeof(struct PasswdInfo));
if (Inst) {
if (UserGroupBase) CloseLibrary(UserGroupBase);
if (SocketBase) CloseLibrary(SocketBase);
if (UtilityBase) CloseLibrary(UtilityBase);
if (DOSBase) CloseLibrary(DOSBase);
}
return 0;
}
void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...)
{
VFPrintf(File,Fmt,(&Fmt)+1);
}
void mystrcat(char *Dest,char *Cat)
{
memcpy(Dest+strlen(Dest),Cat,strlen(Cat)+1);
}
void mymovmem(char *From,char *To,int Len)
{
int Cnt;
if (From > To) {
for (Cnt=0;Cnt < Len;Cnt++) {
To[Cnt]=From[Cnt];
}
} else if (From < To) {
for (Cnt=Len-1;Cnt >= 0;Cnt--) {
To[Cnt]=From[Cnt];
}
}
}
struct Node *FindNode(struct List *List,struct Node *Node)
/* returns Node if Node is a member of list, NULL otherwise */
{
struct Node *ChkNode;
for (ChkNode=List->lh_Head;ChkNode->ln_Succ;ChkNode=ChkNode->ln_Succ) {
if (ChkNode==Node) return Node;
}
return NULL;
}
ULONG FakeBeginIO(void *IORequest)
{
((struct IORequest *)IORequest)->io_Flags &= ~IOF_QUICK; /* Quick IO not supported */
((struct IOExtSer *)IORequest)->io_Status &= ~(1<<0); /* clear abort bit */
((struct Node *)IORequest)->ln_Name=NULL; /* clear possible signature */
PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],IORequest);
return 0;
}
ULONG FakeAbortIO(void *IORequest)
{
struct IOExtSer *Ser;
Ser=IORequest;
Forbid();
Ser->io_Status |= (1<<0); /* Flag the request as aborted */
if (FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[1],Ser) ||
FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[2],Ser)) {
/* This IORequest is waiting to be processed */
Remove(Ser);
Ser->IOSer.io_Error=IOERR_ABORTED;
Ser->IOSer.io_Actual=0;
ReplyMsg(Ser);
}
else {
/* This IORequest is currently being processed -- send a break */
Signal(((struct MsgPort *)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[0])->mp_SigTask,SIGBREAKF_CTRL_C);
}
Permit();
return 0;
}
ULONG FakeOpen(void *IORequest)
{
struct IOExtSer *Ser;
Ser=IORequest;
Forbid();
((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])+1); /* Increment opencnt */
Permit();
Ser->IOSer.io_Error=0;
Ser->io_CtlChar=SER_DEFAULT_CTLCHAR;
Ser->io_RBufLen=(long)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[4];
Ser->io_ExtFlags=0;
Ser->io_Baud=19200;
Ser->io_BrkTime=250000;
Ser->io_TermArray.TermArray0=0;
Ser->io_TermArray.TermArray1=0;
Ser->io_ReadLen=8;
Ser->io_WriteLen=8;
Ser->io_StopBits=1;
Ser->io_Status=0;
return 0;
}
ULONG FakeClose(void *IORequest)
{
struct IOExtSer *Ser;
struct Message *Msg;
Ser=IORequest;
Forbid();
((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])-1); /* Decrement opencnt */
Msg=AllocMem(sizeof(struct Message),MEMF_PUBLIC|MEMF_CLEAR);
Msg->mn_Node.ln_Name=Signature;
PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],Msg);
Permit();
return 0;
}
struct DosPacket *PktFromMsg(struct Message *Msg)
{
return (struct DosPacket *)Msg->mn_Node.ln_Name;
}
void PktFPuts(struct InstData *Inst,BPTR File,char *String)
{
struct MsgPort *ReplyPort;
struct DosPacket *Pkt;
ReplyPort=CreateMsgPort();
Pkt=AllocDosObject(DOS_STDPKT,NULL);
if (!Pkt || !ReplyPort) return;
Pkt->dp_Type=ACTION_WRITE;
Pkt->dp_Arg1=((struct FileHandle *)BADDR(File))->fh_Arg1;
Pkt->dp_Arg2=(LONG) String;
Pkt->dp_Arg3=strlen(String);
Pkt->dp_Port=ReplyPort;
PutMsg(((struct FileHandle *)BADDR(File))->fh_Type,Pkt->dp_Link);
WaitPort(ReplyPort);
GetMsg(ReplyPort);
DeleteMsgPort(ReplyPort);
FreeDosObject(DOS_STDPKT,Pkt);
}
unsigned long GetInt(char *String,char **NewPtr)
{
unsigned long Num=0;
char *Junk;
long Cnt;
long BaseNum;
if (!NewPtr) NewPtr=&Junk;
for (*NewPtr=String;;(*NewPtr)++) {
if (**NewPtr < '0' || **NewPtr > '9') return Num;
/* AAARGH!! multiplication causes a lib call to be generated.
We can't use the library. Therefore we have to add */
/* Num=Num*10; */
for (BaseNum=Num,Cnt=0;Cnt < 9;Cnt++,Num+=BaseNum);
Num+=**NewPtr-'0';
}
}
void SockPuts(struct InstData *Inst,int Sock,char *Buf)
{
int BufPos=0;
int BytesWritten;
do {
BytesWritten=send(Sock,Buf+BufPos,strlen(Buf+BufPos),0);
if (BytesWritten > 0) BufPos+=BytesWritten;
} while (Buf[BufPos]);
}
void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len)
{
int BufPos=0;
int BytesWritten;
if (!Len) return;
do {
BytesWritten=send(Sock,Buf+BufPos,Len-BufPos,0);
if (BytesWritten > 0) BufPos+=BytesWritten;
} while (Len-BufPos);
}
void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag)
{
int Cnt;
int BufPos=0;
unsigned char iac2[2];
char eol[2];
char csi[2];
iac2[0]=iac2[1]=IAC;
eol[0]='\r';
eol[1]='\n';
csi[0]='\x1b';
csi[1]='[';
while (Len > BufPos) {
for (Cnt=BufPos;Cnt < Len;Cnt++) {
if (!RawFlag)
if (Buf[Cnt]=='\r' || Buf[Cnt]=='\n') break;
if (Buf[Cnt]=='\x9b') break;
if (Buf[Cnt]==IAC) {
break;
}
}
SockRawWrite(Inst,Sock,Buf+BufPos,Cnt-BufPos);
BufPos=Cnt;
if (BufPos < Len && Buf[BufPos]==IAC) { /* If we got single IAC, send double IAC */
BufPos++;
SockRawWrite(Inst,Sock,iac2,2);
}
if (!RawFlag) {
if (BufPos < Len && Buf[BufPos]=='\r') {
BufPos++;
}
if (BufPos < Len && Buf[BufPos]=='\n') {
BufPos++;
SockRawWrite(Inst,Sock,eol,2);
}
if (BufPos < Len && Buf[BufPos]=='\x9b') {
BufPos++;
SockRawWrite(Inst,Sock,csi,2);
}
}
}
}
void ParseBuf3(struct InstData *Inst)
/* Parse 3 character remote request */
{
}
void ParseBuf2(struct InstData *Inst)
/* Parse 2 character remote-request */
{
}
void ParseBufSubNegotiate(struct InstData *Inst)
{
}
int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode)
{
int GotLen;
unsigned char Got,TrueGot;
/*RawMode=TRUE;*/
static unsigned char PrevChar;
do {
GotLen=recv(Sock,&Got,1,0); /* Wait for a character */
if (GotLen==-1) {
if (Errno()==EINTR) continue;
else return -1;
} else if (GotLen==0) return 0;
TrueGot=Got;
if (!Inst->RecvBufPos && GotLen==1 && Got==0) GotLen=-1; /* Read again */
if (GotLen==1 && !RawMode && !Inst->RecvBufPos) {
/* These next few lines ignore incoming newlines and convert
incoming CRs into newlines */
if (Got=='\n' && PrevChar=='\r') GotLen=-1; /* Read again. */
if (Got=='\r') Got='\n';
}
} while (GotLen != 1);
/* *Loc=Got;
return 1; */
if (Inst->RecvBufPos) {
Inst->RecvBuf[Inst->RecvBufPos]=Got;
Inst->RecvBufPos++;
switch (Inst->RecvBufPos) {
case 2:
switch(Inst->RecvBuf[1]) {
case IAC:
/* Just a single IAC */
*Loc=IAC;
return 1;
break;
case SB:
Inst->RecvBufFlags|=RBF_SUBNEGOTIATE;
return RecvChar(Inst,Sock,Loc,RawMode);
break;
case SE:
Inst->RecvBufPos=0;
Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
return RecvChar(Inst,Sock,Loc,RawMode);
case WILL:
case WONT:
case DO:
case DONT:
return RecvChar(Inst,Sock,Loc,RawMode);
break;
default:
ParseBuf2(Inst);
Inst->RecvBufPos=0;
return RecvChar(Inst,Sock,Loc,RawMode);
}
break;
default:
if (Inst->RecvBufFlags & RBF_SUBNEGOTIATE) {
if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]!=IAC) {
/* End of subnegotiation */
Inst->RecvBuf[0]=IAC;
if ((Inst->RecvBuf[1]=Inst->RecvBuf[Inst->RecvBufPos-1])==SE) {
Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
Inst->RecvBufPos=0;
return RecvChar(Inst,Sock,Loc,RawMode);
}
Inst->RecvBufPos=2;
ParseBufSubNegotiate(Inst);
}
if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]==IAC) {
/* We just got a double IAC in subnegotiation */
Inst->RecvBuf[Inst->RecvBufPos-2]=-1; /* We store IAC as a (int)-1 */
Inst->RecvBufPos--;
}
return RecvChar(Inst,Sock,Loc,RawMode);
} else {
if (Inst->RecvBuf[2]==IAC) {
/* Restart sequence */
Inst->RecvBuf[0]=IAC;
Inst->RecvBufPos=1;
return RecvChar(Inst,Sock,Loc,RawMode);
} else {
ParseBuf3(Inst);
Inst->RecvBufPos=0;
return RecvChar(Inst,Sock,Loc,RawMode);
}
}
break;
}
}
else {
if (Got==IAC) {
Inst->RecvBuf[0]=Got;
Inst->RecvBufPos=1;
return RecvChar(Inst,Sock,Loc,RawMode);
} else {
*Loc=Got;
PrevChar=TrueGot;
return 1;
}
}
return 1;
}
void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize)
/* This function gets the next string until a CR
on the specified socket, and places it in buf. It
discards leading crs/lfs */
{
int BufPos=0;
int BytesRead;
int FirstBytes=TRUE;
Buf[0]='\0';
do {
BytesRead=RecvChar(Inst,Sock,Buf+BufPos,FALSE);
if (BytesRead < 0) {
if (Errno()!=EINTR) {
Buf[BufPos]='\0';
return;
}
}
else if (BytesRead==0) {
Buf[BufPos]='\0';
return;
}
else {
if ((Buf[BufPos]=='\r' || Buf[BufPos]=='\n') && FirstBytes) {
Buf[BufPos]='\0';
} else {
FirstBytes=FALSE;
BufPos+=BytesRead;
}
}
} while (Buf[BufPos-1] != '\r' && Buf[BufPos-1] != '\n' && BufPos < (BufSize-1));
Buf[BufPos]='\0';
}
char *PullPasswdString(char **StringPtr)
{
int Cnt;
char *RetVal;
char *CurPos;
if (!StringPtr || !*StringPtr) return NULL;
RetVal=*StringPtr;
for (CurPos=RetVal;*CurPos != ',' && *CurPos != '\r' && *CurPos != '\n' && *CurPos;CurPos++);
switch (*CurPos) {
case ',':
case '\r':
case '\n':
*CurPos='\0';
CurPos++;
*StringPtr=CurPos;
return RetVal;
case '\0':
*StringPtr=CurPos;
return RetVal;
}
}
int mystrcmp(char *S1,char *S2)
{
int Cnt;
for (Cnt=0;S1[Cnt] && S2[Cnt];Cnt++) {
if (S1[Cnt] != S2[Cnt]) return !0;
}
if (S1[Cnt] != S2[Cnt]) return !0;
return 0;
}
struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login)
{
BPTR File;
char *LineBuf;
char *BufPtr;
char *PasswdPtr;
char *LoginPtr;
char *RealNamePtr;
char *HomeDirPtr;
char *CmdPtr;
struct PasswdInfo *Info = NULL;
struct passwd *result;
if (result = getpwnam(Login)) {
if (Info=AllocMem(sizeof(struct PasswdInfo),MEMF_PUBLIC)) {
strcpy(Info->Login,result->pw_name);
strcpy(Info->Passwd,result->pw_passwd);
strcpy(Info->RealName,result->pw_gecos);
strcpy(Info->Command,result->pw_shell);
}
else
syslog(LOG_CRIT, "Couldn't allocate my info structure!");
}
else
syslog(LOG_INFO, "user %s is unknown here", Login);
return Info;
}
void __asm PutMLSChar(register __d0 char Chr,register __a3 char **BufPtr)
{
**BufPtr=Chr;
(*BufPtr)++;
}
void MakeLongStr(char *StrBuf,unsigned long Num)
{
RawDoFmt("%lu",&Num,PutMLSChar,&StrBuf);
}
struct Process *MyCreateNewProcTags(struct InstData *Inst,ULONG Tag1,...)
{
return CreateNewProc((struct TagItem *)&Tag1);
}
void *MyAllocDosObjectTags(struct InstData *Inst,ULONG Type,ULONG Tag1,...)
{
return AllocDosObject(Type,(struct TagItem *)&Tag1);
}
void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...)
{
#undef DOSBase
#define DOSBase DSBse
SystemTagList(Cmd,(struct TagItem *)&Tag0);
#undef DOSBase
}
#define DOSBase DSBse
int __asm __saveds SubSubProc(register __a0 char *ArgString,register __d0 long Length)
{
char StringBuf[1000];
char *StringPtr;
BPTR FH;
struct Library *DSBse;
DSBse=OpenLibrary("dos.library",36);
if (!DSBse) return 0;
FH=(BPTR)GetInt(ArgString,&StringPtr);
/* if (IsInteractive(FH)) {
Write(FH,"Interactive\n",12);
}*/
strcpy(StringBuf,StringPtr);
MySystemTags(DSBse,(StringBuf[0]) ? StringBuf : "execute S:remote-startup",
SYS_Input,FH,
SYS_Output,FH,
NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
NP_Cli,TRUE,
TAG_END);
Forbid();
Close(FH);
return 0;
}
#undef DOSBase
@
1.11
log
@Minor cosmetic changes in the source code.
Added "user unknown" to the "getpwnam() failed" message, to
make sure that people don't misunderstand this as an error.
@
text
@d3 2
a4 2
* $Revision: 1.10 $
* $Date: 1995/02/03 00:25:28 $
d7 1
a7 1
* Copyright (C) 1995 by Peter Simons <simons@@peti.GUN.de>
d23 1
a23 1
* $Id: telnetd.c 1.10 1995/02/03 00:25:28 simons Exp simons $
d98 1
a98 1
static const char __DOSVer[] = VERSTAG " written by Peter Simons <simons@@peti.GUN.de>";
d143 1
a143 1
char Buf[1000],LoginBuf[50];
d310 2
d320 4
d358 2
a359 3
NP_Arguments,Buf,
NP_Name,"Telnet subprocess",
TAG_END);
d1527 1
a1527 1
syslog(LOG_DEBUG, "getpwnam() failed, user unknown");
d1578 6
a1583 13
if (!StringBuf[0]) {
MySystemTags(DSBse,"execute s:remote-startup",
SYS_Input,FH,
SYS_Output,FH,
NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
TAG_END);
} else {
MySystemTags(DSBse,StringBuf,
SYS_Input,FH,
SYS_Output,FH,
NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
TAG_END);
}
@
1.10
log
@Modified telnetd to use usergroup.library's routines to access
the passwd file. Thus, I had to insert UserGroupBase into the
Inst-structure holding the various library bases.
Modified telnetd to block any login where the user has no valid
shell provided. Any shell us accepted except "nologin".
Added initializations for syslog().
Reformatted source code a bit.
@
text
@d3 2
a4 2
* $Revision: 1.9 $
* $Date: 1995/01/26 22:20:38 $
d23 1
a23 1
* $Id: telnetd.c 1.9 1995/01/26 22:20:38 simons Exp simons $
d424 2
a425 1
if (Pkt->dp_Res1==Pkt->dp_Arg3 || Chr=='\r' || Chr=='\n') {
d427 3
d538 2
a539 1
if (TimeReq) DeleteIORequest(TimeReq);
d1522 1
a1522 1
syslog(LOG_DEBUG, "getpwnam() failed");
@
1.9
log
@Removed an unnecessary declaration. Doesn't really affect the code.
@
text
@d3 2
a4 2
* $Revision: 1.8 $
* $Date: 1995/01/24 00:12:47 $
d23 1
a23 1
* $Id: telnetd.c 1.8 1995/01/24 00:12:47 simons Exp simons $
d39 1
d48 2
d60 1
d77 1
d79 1
a79 1
#define UtilityBase Inst->UtilityB
d207 2
d212 7
a218 1
if (!DOSBase || !UtilityBase || !SocketBase || !TimePort) return 0;
d287 2
a288 2
Info=LookupPasswd(Inst,LoginBuf);
if (!Info || strcmp(Info->Passwd,"*")) {
d290 25
a314 18
strcpy(Buf,"Password: ");
strcpy(Buf+strlen(Buf),NoEcho);
SockPuts(Inst,Socket,Buf);
SockGets(Inst,Socket,Buf,sizeof(Buf));
while (strlen(Buf) && (Buf[strlen(Buf)-1]=='\n' || Buf[strlen(Buf)-1]=='\r'))
Buf[strlen(Buf)-1]='\0';
SockPuts(Inst,Socket,Echo);
#ifdef DEBUG
FPuts(DebugFile,"Got Password: ");
FPuts(DebugFile,Buf);
FPuts(DebugFile,"\n");
#endif
if (!Info || strcmp(Buf,Info->Passwd)) {
SockPuts(Inst,Socket,"\nLogin incorrect.\nClosing connection\n");
CloseSocket(Socket);
goto quit;
}
}
d1049 1
d1053 1
d1503 2
a1504 5
struct PasswdInfo *Info;
/* int NoPasswd=FALSE; */
LineBuf=AllocMem(1000,MEMF_PUBLIC);
if (!LineBuf) return NULL;
d1506 6
a1511 43
File=Open("AmiTCP:db/telnetd_passwd",MODE_OLDFILE);
if (!File) return NULL;
while (FGets(File,LineBuf,1000)) {
if (LineBuf[0]=='#') continue;
BufPtr=LineBuf;
LoginPtr=PullPasswdString(&BufPtr);
#ifdef DEBUG
FPuts(DebugFile,"Got username: ");
FPuts(DebugFile,LoginPtr);
FPuts(DebugFile,"\n");
#endif
PasswdPtr=PullPasswdString(&BufPtr);
#ifdef DEBUG
FPuts(DebugFile,"Got password: ");
FPuts(DebugFile,PasswdPtr);
FPuts(DebugFile,"\n");
#endif
PullPasswdString(&BufPtr); /* throw away user id */
PullPasswdString(&BufPtr); /* Throw away group id */
RealNamePtr=PullPasswdString(&BufPtr);
HomeDirPtr=PullPasswdString(&BufPtr);
CmdPtr=PullPasswdString(&BufPtr);
/* if (!mystrcmp(PasswdPtr,"*")) NoPasswd=TRUE;*//*strcpy(Passwd,PasswdPtr);*/
/* else NoPasswd=FALSE; */
if (!mystrcmp(Login,LoginPtr)) {
#ifdef DEBUG
FPuts(DebugFile,"Password located\n");
#endif
/* Password located and correct */
/*if (CmdPtr[0]=='*') */ /* We only support stdin/out logins */
Close(File);
Info=AllocMem(sizeof(struct PasswdInfo),MEMF_PUBLIC);
if (!Info) return NULL;
strcpy(Info->Login,LoginPtr);
strcpy(Info->Passwd,PasswdPtr);
strcpy(Info->RealName,RealNamePtr);
strcpy(Info->WorkDir,HomeDirPtr);
strcpy(Info->Command,CmdPtr);
FreeMem(LineBuf,1000);
return Info;
d1513 2
d1516 4
a1519 3
Close(File);
FreeMem(LineBuf,1000);
return NULL; /* Login failed */
@
1.8
log
@Renamed tnserv:passwd to AmiTCP:db/telnetd_passwd.
Renamed tnserv:banner to AmiTCP:db/telnetd_banner.
These names are subject of change.
Re-wrote the routine that copied the banner file to use
Read() rather than FGets().
Change to telnetd to accept if no banner file is available.
Earlier versions would have terminated.
@
text
@d3 2
a4 2
* $Revision: 1.7 $
* $Date: 1995/01/23 23:51:39 $
d23 1
a23 1
* $Id: telnetd.c 1.7 1995/01/23 23:51:39 simons Exp simons $
a92 1
//struct Library *SocketBase;
@
1.7
log
@Renamed the daemon to telnetd. Getty sounds like a BBS. :-)
@
text
@d3 2
a4 2
* $Revision: 1.6 $
* $Date: 1995/01/23 23:42:48 $
d23 1
a23 1
* $Id: telnetd.c 1.6 1995/01/23 23:42:48 simons Exp simons $
d248 10
a257 7
BannerFile=Open("tnserv:banner",MODE_OLDFILE);
if (!BannerFile) goto quit;
#ifdef DEBUG
FPuts(DebugFile,"Opened tnserv:banner\n");
#endif
while (FGets(BannerFile,Buf,sizeof(Buf))) {
SockWrite(Inst,Socket,Buf,strlen(Buf),FALSE);
d259 1
d261 1
a261 1
FPuts(DebugFile,"Wrote tnserv:banner to socket\n");
a1031 1
if (BannerFile) Close(BannerFile);
d1488 1
a1488 1
File=Open("tnserv:Passwd",MODE_OLDFILE);
@
1.6
log
@Adding the weird assignment of the message to the name pointer again.
Obviously, Steve was using this hack as a shurtcut to provide an
additional parameter to a subroutine without having to worry about
adding an entry to his structure. I will fix this some day. Not
very high priority.
@
text
@d2 3
a4 3
* $Filename: TelnetGetty.c $
* $Revision: 1.5 $
* $Date: 1995/01/23 23:35:13 $
d23 1
a23 1
* $Id: TelnetGetty.c 1.5 1995/01/23 23:35:13 simons Exp simons $
d50 1
a50 1
#include "TelnetGetty_rev.h"
d208 2
a209 2
DebugFile=Open("con:0/0/500/100/TelnetGetty DEBUG/WAIT/CLOSE",MODE_OLDFILE);
FPuts(DebugFile,"TelnetGetty starting\n");
@
1.5
log
@Made the Echo[], NoEcho[] and iac2[] arrays unsigned character
to avoid compiler warnings when assigning values above 128.
Removed some multiuser.library stuff.
Minor fix when compiling with USE_INETD: Debug output tried
to print an uninitialized auto variable.
Didn't test the returncode of LookupPasswd(), causing an enforcer
hit when no correct login had been specified.
@
text
@d3 2
a4 2
* $Revision: 1.3 $
* $Date: 1995/01/23 22:19:28 $
d23 1
a23 1
* $Id: TelnetGetty.c 1.3 1995/01/23 22:19:28 simons Exp simons $
d518 1
a518 1
/* TimeReq->tr_node.io_Message.mn_Node.ln_Name=Msg; TODO */
@
1.4
log
@Added several casts to avoid warnings.
Removed weird assignment of an Message structure to the
name field of a TimerRequest. Made no sense to me.
@
text
@d145 2
a146 2
char NoEcho[7];
char Echo[14];
a171 8
/*
Echo[0]=NoEcho[0]=IAC;
Echo[1]=WONT;
Echo[2]=ECHO;
NoEcho[1]=WILL;
NoEcho[2]=ECHO;
Echo[3]=NoEcho[3]='\0';
*/
d209 3
a211 1
FPuts(DebugFile,"TelnetGetty starting\nArgString=");
d214 1
d286 1
a286 1
if (strcmp(Buf,Info->Passwd)) {
a292 19
/*
if (muBase) {
struct TagItem tags[]={
{muT_Graphical,FALSE},
{muT_Task,NULL},
{muT_Global,FALSE},
/*{muT_Quiet,FALSE},*/
/* {muT_All,FALSE}, */
{muT_UserID,NULL},
{muT_Password,NULL},
{TAG_END,0}
};
tags[1].ti_Data=FindTask(NULL);
tags[5].ti_Data=LoginBuf;
tags[6].ti_Data=Buf;
muLoginA(tags);
}
*/
d1226 1
a1226 1
char iac2[2];
d1558 1
@
1.3
log
@Fixed a bug when compiling in USE_INETD mode: The ReadWaitList-
queue hasn't been initialized. Moved the NewList() out of the
#ifdef-#else statement to fix this.
@
text
@d3 2
a4 2
* $Revision: 1.2 $
* $Date: 1995/01/23 21:59:56 $
d23 1
a23 1
* $Id: TelnetGetty.c 1.2 1995/01/23 21:59:56 simons Exp simons $
d224 1
a224 1
Self=FindTask(NULL);
d251 1
d542 1
a542 1
TimeReq->tr_node.io_Message.mn_Node.ln_Name=Msg;
d579 1
a579 1
for (GotMsg=ReadWaitList.lh_Head;GotMsg->mn_Node.ln_Succ;GotMsg=(struct Message *)GotMsg->mn_Node.ln_Succ) {
d1186 1
a1186 1
Pkt->dp_Arg2=String;
d1623 1
@
1.2
log
@Made source compile with SAS/C 6.51.
Restructured source code basically and added GNU copyleft header.
Renamed SubProcCode() to main().
Removed some multiuser.library stuff.
@
text
@d3 2
a4 2
* $Revision$
* $Date$
d23 1
a23 1
* $Id$
d98 1
a98 1
const char *Signature="FAKEMSG--EXPUNGE";
d212 1
a228 1
a230 1
NewList(&ReadWaitList);
@
1.1
log
@Initial revision
@
text
@d1 25
a25 1
/* #define CLIB_SOCKET_INLINES_H / * avoid that include file */
d27 1
d32 1
a48 4
/*#include <libraries/multiuser.h>
#include <proto/multiuser.h>
*/
/* IMPORTANT: Do NOT link this module with the startup code */
d50 3
a60 2
/* Defines for RecvBufFlags: */
#define RBF_SUBNEGOTIATE (1<<0)
d63 7
a69 8
#undef DEBUG
struct Library *SocketBase; /* Linker wants it. We don't use it */
#ifndef USE_INETD
struct Library *SysBase;
#endif
const char *Signature="FAKEMSG--EXPUNGE";
d71 1
d90 9
a98 7
struct PasswdInfo {
char Login[50];
char Passwd[50];
char RealName[150];
char WorkDir[256];
char Command[512];
};
d100 1
d125 1
a125 2
#define bzero(base,n) memset(base,0,n)
#define bcopy(from,to,n) memcpy(to,from,n)
a129 1
/* SubProcCode MUST be the first function in the file */
d131 1
a131 1
void main(void)
d133 1
a133 1
int __asm SubProcCode(register __a0 char *ArgStr,register __d0 long Length)
a163 1
/*struct Library *muBase=NULL;*/
a210 3
/* muBase=OpenLibrary("multiuser.library",39);*/
d1588 1
a1588 1
int __asm SubSubProc(register __a0 char *ArgString,register __d0 long Length)
@